class EventBus {
  constructor() {
    this.eventMap = {};
  }

  on(eventName, fn) {
    const eventFns = this.eventMap[eventName];
    if (!eventFns) {
      this.eventMap[eventName] = [];
    }
    this.eventMap[eventName].push(fn);
  }

  off(eventName, fn) {
    const eventFns = this.eventMap[eventName];
    if (!eventFns) {
      throw new Error(`没有事件 ${eventName}！`);
    }
    for (let i = 0; i < eventFns.length; i++) {
      const cur = eventFns[i];
      if (cur === fn) {
        this.eventMap[eventName].splice(i, 1);
        break;
      }
    }
    if (eventFns.length === 0) {
      delete this.eventMap[eventName];
    }
  }

  emit(eventName, ...args) {
    const eventFns = this.eventMap[eventName];
    if (!eventFns) {
      throw new Error(`没有事件 ${eventName}！`);
    }
    for (const fn of eventFns) {
      fn(...args);
    }
  }
}
